home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-10-02 | 55.7 KB | 1,931 lines |
- !
- ! CONTROL.SCR
- !
- ! This script manages some independent functions of the game system. The
- ! script is called by the game driver at certain points during game play,
- ! and the entry points are numeric (@0, @1, @2..) instead of the usual entry
- ! points (@TALK, @GET, ..).
- !
- ! QUICK SUMMARY OF ENTRY POINTS:
- !
- ! :@0 - Time Control. Executed once every minute of game time.
- ! (See 'MOVES_PER_MINUTE' parameter)
- !
- ! :@1 - PLAYER MOVES Invoked for each PLAYER during a FIGHT
- !
- ! :@2 - MONSTER MOVES Invoked once to move every monster at
- ! once during a fight (not once for each
- ! monster)
- !
- ! :@3 - Keyboard/Mouse Event. Called every time a KEY is pressed or a mouse
- ! button clicked during normal game play.
- !
- ! :@4 - POSITION MONSTER Invoked once to position the NPCs for
- ! a fight before MONSTER MOVES is called
- ! for the first time.
- !
- !---------------------------------------------------------------------------!
- :@0 ! Entry Point @0 : Time Control Script !
- !---------------------------------------------------------------------------!
- !
- ! This script will start execution at this label once per 'minute' during
- ! regular play. The variable GROUP.MOVES contains the total number of
- ! moves the party has made since the begining of the game. A minute is
- ! defined by the current value of the variable 'MovesPerMinute'
- !
- ! Time is controled by seting the following variables from any script:
- !
- ! Variable Default Description
- ! ------------------- ------- --------------------------------
- ! MovesPerMinute 2 # of moves per game 'minute'
- ! MinutesInAnHour 60 # of minutes in an game 'hour'
- ! HoursInADay 24 # of hour in a game 'day'
- ! DaysInAMonth 30 # of days in a game 'month'
- ! MonthsInAYear 12 # of months in a game 'year'
- !
- ! The CURRENT time is obtained (and modified) by setting the following
- ! variables:
- !
- ! year Current Year (Range -32767 to 32767)
- ! month Current Month (Range 0 to MonthsInAYear - 1)
- ! day Current Day (Range 0 to DaysInAMonth - 1)
- ! hour Current Hour (Range 0 to HoursInADay - 1)
- ! minute Current Minute (Range 0 to MinutesInADay - 1)
- !
-
- ! Update the clock, one more minute has passed !
-
- gosub CLOCK_TICK;
- if minute = 0 gosub CLOCK_PRINT;
-
- ! No perform some time dependent actions
- ! First, save our original status just in case we need it later..
- L255 = group.current; ! Save current party spokesperson !
- L254 = FALSE; ! Have NOT created a random monster !
-
- ! THINGS TO DO EVERY MINUTE
- if group.energy > 0 then
- dec( group.energy );
- ! In the desert, during the day, you consume energy twice as fast
- if world.density(L0,L1) = DESERT and group.vehicle.count = 0 then
- if hour > sunrise and hour < sunset then
- dec( group.energy );
- endif;
- endif;
- if L2 = SWAMP and group.vehicle.count = 0 then
- if random(5) = 0 then ! one out of 5 !
- L255 = group.current;
- foreach player do
- if not player.poisoned then
- player.poisoned = (random(3) = 0); ! one out of 3 !
- if player.poisoned then
- writeln( player.name, " got poisoned by swamp gas!" );
- endif;
- endif;
- endfor;
- group.current = L255; ! Restore the current spokesperson !
- endif;
- endif;
- endif;
-
- ! THINGS TO DO ONCE AN HOUR
- if minute = 0 then
- ! Create a random monster 1 out of every 5 times (approx) !
- if random(5) = 0 then
- if world.type = OUTDOORS or world.type = DUNGEON or world.type = HAUNTED then
- gosub NEWMONSTER;
- endif;
- endif;
-
- ! Check to see if you have food.. !
- if group.food <= group.size then
- if group.food = 0 then
- writeln( "You have no food.." );
- else
- writeln( "You are running out of food.." );
- endif;
- endif;
- endif;
-
- ! Every quarter of an hour !
- L25 = max(MinutesInAnHour / 4 + 1,2);
- if minute % L25 = 0 then
- ! Group must rest within 2 hours or start suffering damage !
- if group.energy < MinutesInAnHour * 2 then
- if group.energy > 0 then
- writeln( "You must rest soon.." );
- else
- writeln( "You are exhausted.." );
- endif;
- endif;
- ! Check for poison, hunger and exhaustion !
- foreach player do
- if player.hp > 0 then
- if player.poisoned then
- s0 = "poisoning";
- gosub HITPLAYER;
- elsif player.energy = 0 and group.food = 0 then
- s0 = "hunger";
- gosub HITPLAYER;
- elsif group.energy <= 0 then
- s0 = "exhaustion";
- gosub HITPLAYER;
- endif;
- endif;
- endfor;
- endif;
-
- !
- ! The following controls healing and recovery of power. You can
- ! change the rate of healing by using a different value, but remember
- ! that the power heal value (8 below) should be a MULTIPLE of the
- ! first number (4) or it will not work.
- !
- if minute % 4 = 0 and group.energy > 0 then
- foreach player do
- if group.food or player.energy then
- gosub HEAL_HP;
- ! Every 8 (twice as slow) restore power
- if minute % 8 = 0 then
- gosub HEAL_PWR;
- endif;
- endif;
- endfor;
- endif;
-
- ! Go back with same selected spokesperson.. !
- group.current = L255;
- CONTINUE;
-
- !---------------------------------------------------------------------------!
- :@1 ! PLAYER MOVES DURING A FIGHT
- !---------------------------------------------------------------------------!
- !
- frame(player.x,player.y,SYS_FRAME);
- write( player.name, " - " );
- if player.hp < 2 then
- if player.hp = 1 then writeln( "is unconscious!" );
- else writeln( "is dead!" );
- endif;
- elsif player.paralyzed then
- writeln( "is paralyzed!" );
- elsif player.scared then
- writeln( "is scared!" );
- else
- stats(player);
- keypress = GET_ACTION;
- frame(player.x,player.y,-SYS_FRAME);
- goto :@3;
- endif;
- frame(player.x,player.y,-SYS_FRAME);
- STOP;
-
- !---------------------------------------------------------------------------!
- :@2 ! Move NPCs during a fight
- !---------------------------------------------------------------------------!
- runscript( "FIGHTING", 1 );
- stop;
-
- !---------------------------------------------------------------------------!
- :@4 ! Position NPCs before a fight
- !---------------------------------------------------------------------------!
- runscript( "FIGHTING", 0 );
- stop;
-
- !---------------------------------------------------------------------------!
- :@3 ! Keyboard Map Entry Point : Process a key press
- !---------------------------------------------------------------------------!
-
- !
- ! THE FOLLOWING TABLE IS A SHORT LIST OF THE VALUES ASSOCIATED WITH EACH
- ! KEY. NOTE THAT SPECIAL KEYS HAVE BEEN MAPPED TO DISTINCT NUMBERS TO
- ! AVOID USING THE WIERD PC KEY VALUES.
-
- ! CTRL +A to Z = 1 to 26
- ! ESCape key = 27
- ! space = 32
- ! 0-9 = 48 to 57
- ! A-Z = 65 to 90
- ! a-z = 65 to 90 (i.e. NO LOWERCASE)
- ! F1 - F10 = 131 to 140
- ! Shift+F1 - F10 = 141 to 150
- ! Ctrl +F1 - F10 = 151 to 160
- ! ALT +F1 - F10 = 161 to 170
- ! ALT +1 to 10 = 171 to 180
- ! ALT +A to Z = 201 to 226
- !
- ! KEY PAD VALUES (arrow keys!):
- ! HOME = 190 ! CTRL + HOME = 187
- ! END = 191 ! CTRL + END = 186
- ! UP = 192 ! CTRL + UP = 230
- ! DOWN = 193 ! CTRL + DOWN = 231
- ! LEFT = 194 ! CTRL + LEFT = 184
- ! RIGHT = 195 ! CTRL + RIGHT = 185
- ! PGUP = 196 ! CTRL + PGUP = 189
- ! PGDN = 197 ! CTRL + PGDN = 188
- ! INS = 198
- ! DEL = 199
- !
- ! When you use the mouse to click on something, the variable BUTTON
- ! contains which button you clicked (1=Left, 2=Right, 3=Middle), and
- ! the rest of the information is obtained as follos:
- !
- ! VALUE OF KEYPRESS Value of POINTX Value of POINTY
- ! ----------------- ------------------ ------------------
- ! VIEW_CLICK 235 World X coordinate World Y coordinate
- ! MENU_CLICK 236 Menu Offset Menu Choice (0 to n)
- ! ICON_CLICK 237 0-7 icon position 0-n block # in blocks file
- ! STAT_CLICK 238 6 (group was shown) Member selected 1-6
- ! 0-5 (member shown) Clicked Item:
- ! 0 = no particular place
- ! 1 = worn weapon location
- ! 2 = worn shield location
- ! 3 = worn armor location
- ! 4 = worn staff location
- ! 5 = worn ring location
- ! 6 = worn amulet location
- ! 7 = Item # 1 in backpack
- ! 8 = Item # 2 in backpack
- ! ....
- ! 22 = Item # 16 in backpack
- !
- if KEYPRESS = 27 then
- if fighting then
- writeln( "Trying to escape.." );
- fight( STOP );
- endif;
- endif;
- if KEYPRESS >= 65 and KEYPRESS <= 90 then
- on KEYPRESS - 65 goto
- LETTER_A, LETTER_B, LETTER_C, LETTER_D, LETTER_E,
- LETTER_F, LETTER_G, LETTER_H, LETTER_I, LETTER_J,
- LETTER_K, LETTER_L, LETTER_M, LETTER_N, LETTER_O,
- LETTER_P, LETTER_Q, LETTER_R, LETTER_S, LETTER_T,
- LETTER_U, LETTER_V, LETTER_W, LETTER_X, LETTER_Y, LETTER_Z;
- endif;
- if KEYPRESS >= 48 and KEYPRESS <= 57 then
- on KEYPRESS - 48 goto
- DIGIT_0, DIGIT_1, DIGIT_2, DIGIT_3, DIGIT_4,
- DIGIT_5, DIGIT_6, DIGIT_7, DIGIT_8, DIGIT_9;
- endif;
- if KEYPRESS = 32 goto SPACE;
- ! KEYPAD ARROWS !
- if KEYPRESS >= 190 and KEYPRESS <= 197 then
- on KEYPRESS - 190 goto
- MOVE_UL, MOVE_DL, MOVE_UP, MOVE_DN, MOVE_LF, MOVE_RT, MOVE_UR, MOVE_DR;
- endif;
- if KEYPRESS >= 235 and KEYPRESS <= 240 then
- on KEYPRESS - 235 goto
- VIEW_CLICK, MENU_CLICK, ICON_CLICK, STAT_CLICK;
- endif;
- ! F1 - F10 = 131 to 140
- if keypress >= 131 and keypress <= 140 then
- on keypress - 131 goto FKEY1,FKEY2,FKEY3,FKEY4,FKEY5,FKEY6,FKEY7,FKEY8,FKEY9,FKEY10;
- endif;
-
- ! Not handled by the script. The driver takes the default action !
- CONTINUE;
-
- :DIGIT_0
- STATS(-2); ! Display GROUP statistics !
- STOP;
-
- :DIGIT_1 :DIGIT_2 :DIGIT_3 :DIGIT_4 :DIGIT_5 :DIGIT_6
- GROUP.CURRENT = KEYPRESS - 49; ! Use 0 to 5 instead of 1 to 6 !
- STATS( GROUP.CURRENT ); ! Display INDIVIDUAL statistics !
- STOP;
-
- :DIGIT_7
- STOP;
-
- :DIGIT_8
- STOP;
-
- :DIGIT_9
- STOP;
-
- :LETTER_A
- write( "Attack: " );
- L3 = locate;
- if failure then
- goto NOTHING;
- endif;
- if npc.count then ! Attack a character !
- writeln( npc.class );
- if fighting then
- goto ATTACK_NPC; ! if we ARE fighting, go do it.. !
- else
- if npc.type <> HOSTILE then
- writeln( "Find some bad guys to fight!" );
- STOP;
- endif;
- endif;
- FIGHT; ! START FIGHT MODE. SCRIPT EXECUTION ENDS HERE !
- endif;
- if object.count then
- if object.type = CHEST then
- if object.locktype then
- writeln( "Instead of fighting it, try 'UNLOCK'!" );
- else
- writeln( "It's not even locked, why fight it?" );
- endif;
- else
- writeln( "Why would you want to fight the ", object.name );
- endif;
- endif;
- STOP;
-
- :LETTER_B
- STOP;
-
- !------------------------------------------------------------------------!
- :LETTER_C ! CAMP OUT !
- !
- ! First, all temporary magical effects are eliminated by reducing any
- ! attribute that exceeds the maximum value for the same attribute.
- !
- ! Armor, Shields, Rings and Amulets re-apply their effect (if any).
- !
- ! The group rests for a third of a day, in one hour increments. For
- ! each hour rested, the group gains 4 hours of 'wake-up' energy. This
- ! means the group should be able to go one and a third days without
- ! sleep.
- !
- ! Random monsters may appear, but not too often.
- !
- if fighting then
- writeln( "This is not a good time to rest.." );
- stop;
- endif;
- frame( group.x, group.y, 10 ); ! ZZZZ.... !
- write( "Resting" );
- voice( "snore", 1000 );
- L255 = group.current; ! Save current party spokesperson !
- L254 = FALSE; ! Have NOT created a random monster !
- foreach player do
- gosub NEW_LEVEL; ! Figure out if character went up one level !
- write(".");
- ! First, get rid of temporary magical increases in attributes !
- player.str = min(player.str,player.mstr);
- player.aim = min(player.aim,player.maim);
- player.dex = min(player.dex,player.mdex);
- player.spd = min(player.spd,player.mspd);
- player.pwr = min(player.pwr,player.mpwr);
- player.hp = min(player.hp, player.mhp);
- player.iq = min(player.iq, player.miq);
- player.ac = min(player.ac, player.mac);
- if player.armor.count or player.shield.count then
- if player.armor.cursed or player.shield.cursed then
- player.ac = 0;
- else
- inc( player.ac, player.armor.ac + player.shield.ac );
- endif;
- endif;
- if player.ring.count and player.ring.charges then
- curritem = player.ring;
- gosub M1_INVOKE;
- endif;
- if player.amulet.count and player.amulet.charges then
- curritem = player.amulet;
- gosub M1_INVOKE;
- endif;
- endfor;
- ! # of hours to rest is one third of a day !
- for L253 = 1 to HoursInADay / 3 + 1 do
- write(".");
- ! Each hour of sleep gives 4 hours of energy !
- if group.energy + MinutesInAnHour * 4 > 32767 then
- group.energy = 32767;
- else
- inc( group.energy, MinutesInAnHour * 4 );
- endif;
- for L252 = 0 to MinutesInAnHour / 2 do
- gosub CLOCK_TICK;
- gosub CLOCK_TICK;
- foreach player do
- if group.food or player.energy then
- gosub HEAL_HP;
- if L252 % 2 then
- gosub HEAL_PWR;
- endif;
- endif;
- endfor;
- endfor;
- ! Check to see if random monsters appear !
- if world.type = OUTDOORS or world.type = DUNGEON or world.type = HAUNTED then
- if random(17) = 0 then
- gosub NEWMONSTER;
- if L254 then
- frame( group.x, group.y, -1 ); ! Restore !
- writeln( "You wake up under attack.." );
- FIGHT; ! Wake up and fight.. !
- endif;
- endif;
- endif;
- endfor;
- group.current = L255; ! Go back to original spokes person !
- frame( group.x, group.y, -1 ); ! Restore !
- voice( "CHIMES", 1000 );
- gosub CLOCK_PRINT;
- STOP;
-
- :LETTER_D
- write( "Drop " );
- L0 = select$n( player );
- stats(-1);
- if L0 >= 0 then
- writeln( player.bp.name );
- runscript( player.bp.script, "CURRITEM", DROP );
- ! Does NOT return !
- endif;
- writeln( "nothing.." );
- if L0 < -1 then
- writeln( "You are not carrying anything!" );
- endif;
- STOP;
-
- :LETTER_E
- if group.vehicle.count then ! Must be on foot !
- writeln( "You must be on foot to enter/exit worlds.." );
- STOP;
- endif;
- if group.x <> 0 or group.y <> 0 then
- for L0 = 0 to 31 do
- if world.doorx(L0) = group.x and world.doory(L0) = group.y then
- world.door = L0; ! Use this door !
- writeln( "Please wait..." );
- runscript( WORLD, "WORLDDEF", EXIT );
- ! Should not return !
- endif;
- endfor;
- endif;
- writeln( "There is no door here.." );
- STOP;
-
- :LETTER_F
- STOP;
-
- :LETTER_G
- ! Get !
- if player.hp > 1 then
- write( "Get " );
- L0 = locate( object ); ! Find OBJECT only, no people !
- if success then
- writeln( object.type );
- if L0 < 2 then
- runscript( object.script, "OBJECT", GET );
- ! Does NOT return !
- else
- writeln( "You can't reach the ", object.type );
- endif;
- else
- goto NOTHING;
- endif;
- else
- write( player.name, " can't get anything.." );
- endif;
- STOP;
-
- :LETTER_H
- STOP;
-
- :LETTER_I
- display$n( player );
- STOP;
-
- :LETTER_J
- STOP;
-
- :LETTER_K
- STOP;
-
- :LETTER_L
- write( "Look at " );
- L0 = locate; ! Find ANYTHING !
- if success then
- if npc.count then ! Found an NPC !
- writeln( npc.type );
- runscript( npc.script, "OBJECT", LOOK );
- endif;
- writeln( object.type );
- runscript( object.script, "OBJECT", LOOK );
- endif;
- goto NOTHING;
-
- :LETTER_M
- STOP;
-
- :LETTER_N
- write( "Invoke " );
- L0 = select$n( player, SCROLL, GEMS );
- stats(-1);
- if L0 >= 0 then
- runscript( player.bp.script, "CURRITEM", INVOKE );
- ! Does NOT return !
- endif;
- writeln( "nothing .." );
- if L0 < -1 then
- writeln( "You have no items that you can invoke.." );
- endif;
- STOP;
-
- :LETTER_O
- STOP;
-
- :LETTER_P
- STOP;
-
- :LETTER_Q
- write( "Quaff (eat or drink) " );
- L0 = select$n( player, FOOD, POTION );
- stats(-1);
- if L0 >= 0 then
- runscript( player.bp.script, "CURRITEM", INVOKE );
- ! Does NOT return !
- endif;
- writeln( "nothing .." );
- if L0 < -1 then
- writeln( "You have no items that you can eat or drink" );
- endif;
- STOP;
-
- :LETTER_R
- write( "Remove " );
- L0 = select( player.body ); ! Any worn item !
- stats(-1);
- if L0 >= 0 then
- runscript( player.body.script, "CURRITEM", REMOVE );
- endif;
- writeln( "nothing.." );
- if L0 < -1 then
- writeln( "You have no items to remove!" );
- endif;
- STOP;
-
- :LETTER_S
- runscript( player.script, "CASTING", CAST );
- STOP;
-
- :LETTER_T
- write( "Talk to " );
- L0 = locate; ! Find ANYTHING !
- if success then
- if npc.count then ! Found an NPC !
- if abs(npc.x - player.x) > 2 or abs(npc.y - player.y) > 2 then
- writeln( "You must get closer!" );
- STOP;
- endif;
- writeln( npc.type );
- runscript( npc.script, "OBJECT", TALK );
- endif;
- if abs(object.x - player.x) > 2 or abs(object.y - player.y) > 2 then
- writeln( "You must get closer!" );
- STOP;
- endif;
- writeln( object.type );
- runscript( object.script, "OBJECT", TALK );
- endif;
- if group.x = pointx and group.y = pointy then
- writeln( "yourself..?" );
- else
- writeln( "no one.." );
- endif;
- STOP;
-
- :LETTER_U
- write( "Use " );
- L0 = locate( OBJECT ); ! Find an object !
- if success then
- if abs(object.x - player.x) > 2 or abs(object.y - player.y) > 2 then
- writeln( "You must get closer!" );
- STOP;
- endif;
- writeln( object.type );
- runscript( object.script, "OBJECT", USE );
- endif;
- goto NOTHING;
-
- :LETTER_V
- if group.size > 1 then
- writeln( "Who leaves the party?" );
- L0 = select( group );
- stats(-1);
- if player.index = 0 then
- writeln( "You can't leave the party!" );
- STOP;
- endif;
- if player.hp = 0 then
- writeln( "You leave ", player.name, "'s body to the vultures.." );
- elsif player.hp < 2 then
- writeln( "You abandon ", player.name, ", who is almost dead.." );
- else
- writeln( player.name, " leaves the group." );
- endif;
- LEAVE(player.index);
- stats(-1);
- else
- writeln( "You are alone!" );
- endif;
- STOP;
-
- :LETTER_W
-
- write( "Wear (or Wield) " );
- L0 = select$n( player, WEAPON, ARMOR, RING, AMULET, STAFF );
- stats(-1);
- if L0 >= 0 then
- runscript( player.bp.script, "CURRITEM", WEAR );
- ! Does NOT return !
- endif;
- writeln( "nothing .." );
- if L0 < -1 then
- writeln( "You have no items that you can wear or wield" );
- endif;
- STOP;
-
- :LETTER_X
- if group.vehicle.count then
- ! We are riding on a vehicle !
- curritem = group.vehicle;
- runscript( group.vehicle.script, "CURRITEM", EXIT );
- else
- writeln( "You are already on foot!" );
- endif;
- STOP;
-
- :LETTER_Y
- STOP;
-
- :LETTER_Z
- if player.staff.count then
- curritem = player.staff;
- runscript( player.staff.script, "CURRITEM", invoke );
- endif;
- STOP;
-
- :NOTHING
- if group.x = pointx and group.y = pointy then
- writeln( "yourself..?" );
- else
- writeln( "nothing.." );
- endif;
- STOP;
-
- :SPACE
- writeln( "Pass.." );
- goto @0; ! Time Control !
-
- :VIEW_CLICK
- ! Did we click on ourselves? !
- if group.x = pointx and group.y = pointy then
- writeln( "Don't do that! It tickles.." );
- STOP;
- endif;
- ! First, check the objects !
- L2 = locate( object, pointx, pointy );
- if success then
- if button = 1 then
- if abs(pointx - player.x) > 1 or abs(pointy - player.y) > 1 then
- writeln( "You can't reach the ", object.type );
- STOP;
- endif;
- if object.type = VEHICLE or object.type = DOOR or
- object.type = SIGN or
- object.type = CHEST and object.locktype > 0 then
- writeln( "Use ", object.type );
- runscript( object.script, "OBJECT", USE );
- else
- writeln( "Get ", object.type );
- runscript( object.script, "OBJECT", GET );
- endif;
- elsif button = 2 then
- writeln( "Look at ", object.type );
- runscript( object.script, "OBJECT", LOOK );
- else
- writeln( "The middle button has no effect!" );
- stop;
- endif;
- endif;
- ! Next check the characters !
- L2 = locate( npc, pointx, pointy );
- if success then
- if button = 1 then
- if abs(pointx - player.x) > 2 or abs(pointy - player.y) > 2 then
- writeln( "You must get nearer for conversation." );
- STOP;
- endif;
- writeln( "Talk to ", npc.type );
- runscript( npc.script, "OBJECT", TALK );
- elsif button = 2 then
- writeln( "Look at ", npc.type );
- runscript( npc.script, "OBJECT", LOOK );
- else
- writeln( "The middle button has no effect!" );
- endif;
- endif;
- STOP;
-
- :MENU_CLICK
- ! I don't do anything with this right now.. !
- STOP;
-
- :ICON_CLICK
- on pointx goto
- LETTER_A, ! Attack !
- LETTER_G, ! Get !
- LETTER_D, ! Drop !
- LETTER_L, ! Look !
- LETTER_T, ! Talk !
- LETTER_C, ! Camp Out or Sleep !
- LETTER_E, ! Enter or Exit through a door !
- LETTER_I; ! INVENTORY !
- STOP;
-
- :STAT_CLICK
- if pointx = 6 and pointy < group.size then
- ! Looking at Group, selected an individual !
- GROUP.CURRENT = pointy;
- STATS( GROUP.CURRENT ); ! Display INDIVIDUAL statistics !
- else
- ! Looking at Individual (point x), clicked at item)
- on pointy goto
- SHOW_GRP, ! No item, so go back to showing the GROUP
- SHOW_WPN, ! Clicked at weapon being worn (or empty place)
- SHOW_SHLD, ! Clicked at shield being worn (or empty place)
- SHOW_ARMR, ! Clicked at armor being worn (or empty place)
- SHOW_STF, ! Clicked at staff being worn (or empty place)
- SHOW_RING, ! Clicked at ring being worn (or empty place)
- SHOW_AMULET; ! Clicked at amulet being worn (or emtpy place)
- ! No, Clicked at item in the back pack !
- if pointy > 6 and pointy < 22 then
- setbp( player, pointy - 7 );
- gosub DO_BP_ITEM;
- endif;
- endif;
- STOP;
-
- :SHOW_GRP
- stats(6); STOP;
-
- :SHOW_WPN
- if player.weapon.count then
- curritem = player.weapon;
- gosub DO_WORN_ITEM;
- endif;
- STOP;
-
- :SHOW_SHLD
- if player.shield.count then
- curritem = player.shield;
- gosub DO_WORN_ITEM;
- endif;
- STOP;
-
- :SHOW_ARMR
- if player.armor.count then
- curritem = player.armor;
- gosub DO_WORN_ITEM;
- endif;
- STOP;
-
- :SHOW_STF
- if player.staff.count then
- curritem = player.staff;
- gosub DO_WORN_ITEM;
- endif;
- STOP;
-
- :SHOW_RING
- if player.ring.count then
- curritem = player.ring;
- gosub DO_WORN_ITEM;
- endif;
- STOP;
-
- :SHOW_AMULET
- if player.amulet.count then
- curritem = player.amulet;
- gosub DO_WORN_ITEM;
- endif;
- STOP;
-
- :DO_WORN_ITEM
- if button = 1 then
- writeln( "Remove ", curritem.type, ".." );
- runscript( curritem.script, "CURRITEM", REMOVE );
- elsif button = 2 then
- writeln( "Look at ", curritem.type );
- runscript( curritem.script, "CURRITEM", LOOK );
- endif;
- return;
-
- :DO_BP_ITEM
- if player.bp.count then
- curritem = player.bp;
- if button = 1 then
- if curritem.type = WEAPON or curritem.type = ARMOR or
- curritem.type = RING or curritem.type = AMULET or
- curritem.type = SHIELD or curritem.type = STAFF then
- writeln( "Wear/Wield ", curritem.type, ".." );
- runscript( curritem.script, "CURRITEM", WEAR );
- else
- writeln( "Use ", curritem.type, ".." );
- runscript( curritem.script, "CURRITEM", USE );
- endif;
- elsif button = 2 then
- writeln( "Look at ", curritem.type );
- runscript( curritem.script, "CURRITEM", LOOK );
- endif;
- endif;
- return;
-
- !---------------------------------------------------------------------------!
- !---------------------------------------------------------------------------!
- !---------------------------------------------------------------------------!
- !---------------------------------------------------------------------------!
- !---------------------------------------------------------------------------!
- !
- ! SUBROUTINE: HEAL_HP
- !
- ! Heal the players with the passage of time
- !
- :HEAL_HP
- ! alive and not sick !
- if player.hp > 0 and not player.poisoned then
- dec( player.energy );
- if player.energy <= 0 then
- if group.food > 0 then
- dec( group.food );
- player.energy = 255;
- else
- writeln( player.name, " goes hungry!" );
- return;
- endif;
- endif;
- if player.hp < player.mhp then
- inc( player.hp );
- endif;
- endif;
- return;
-
- !
- ! SUBROUTINE: HEAL_PWR
- !
- ! Restore magic points withthe passage of time..
- !
- :HEAL_PWR
- if player.hp > 0 and player.energy > 0 and player.pwr < player.mpwr then
- inc( player.pwr );
- if player.class = ELF and player.pwr < player.mpwr then
- inc( player.pwr ); ! Do elves faster.. !
- endif;
- endif;
- return;
-
- !
- ! SUBROUTINE to create a Random Monster
- !
- :NEWMONSTER
- ! Try to find a position for the monster up to 8 times..
- for L3 = 1 to 8 do
- L0 = group.x + random(8) - 4;
- L1 = group.y + random(8) - 4;
- if L0 < 0 then L0 = 0; endif;
- if L1 < 0 then L1 = 0; endif;
- if L0 >= world.x then L0 = world.x - 1; endif;
- if L1 >= world.y then L1 = world.y - 1; endif;
- if L0 <> player.x or L1 <> player.y then
- L2 = world.density(L0,L1);
- if L2 = FLAT or L2 = ROUGH or L2 = VERY_ROUGH or L2 = SWAMP or L2 = DESERT then
- ! Create a LAND-BASED monster !
- L2 = random(3); ! Small, Medium or Large (0-2) !
- L3 = random(L2+3); ! Select a graphics block for that size (0-4) !
- if world.type = DUNGEON then
- L4 = DEFCAVEBLK( L3 ); ! Leader !
- L5 = DEFCAVEBLK( random(L3+1) ); ! Follower !
- L6 = CAVE_MONSTER;
- elsif world.type = HAUNTED then
- L4 = DEFSPOOKBLK( L3 ); ! Leader !
- L5 = DEFSPOOKBLK( random(L3+1) ); ! Follower !
- L6 = SPOOK_MONSTER;
- else
- ! OUTDOORS or ARENA !
- L4 = DEFLANDBLK( L3 ); ! Leader !
- L5 = DEFLANDBLK( random(L3+1) ); ! Follower !
- L6 = LAND_MONSTER;
- endif;
- goto DOIT;
- elsif L2 = DEEP_WATER then
- ! Create a WATER-BOUND monster !
- L2 = random(3); ! Small, Medium, Large (0-2) !
- if random(5) = 0 then ! Pirate Ship (SPECIAL CASE) !
- L4 = DEFWATERBLK(4); ! Fifth water monster is a ship !
- L5 = DEFWATERBLK(4); ! Followers are ships also !
- else
- L3 = random(L2+2); ! Select a graphics block for that size (0-3) !
- L4 = DEFWATERBLK( L3 ); ! Leader !
- L5 = DEFWATERBLK( random(L3+1) ); ! Follower !
- endif;
- L6 = WATER_MONSTER;
- goto DOIT;
- endif;
- endif;
- endfor;
- return; ! Tried 8 Times, give up !
-
- :DOIT
- new(npc,L0,L1,L4);
- npc.type = HOSTILE; ! NPC Type
- npc.stats = defstat(L2); ! Statistics Record
- npc.block2 = L5; ! Followers (if any)
- npc.class = L6; ! Monster Class
-
- ! Gold carried
- if world.type = ARENA then
- npc.value = random(50)+1; ! Very little money (Up to 5 gold pieces) !
- else
- npc.value = 0;
- endif;
-
- !
- ! # of monsters in the group. The formula is based on L2 (monster size).
- ! If small (L2=0), then # = random( group.size + 6 ) + 1
- ! If medium (L2=1), then # = random( group.size + 3 ) + 1
- ! if large (L2=2), then # = random( group.size ) + 1
- npc.count = random( group.size + (2 - L2) * 3 ) + 1;
-
- L254 = TRUE; ! Monster has been created !
-
- voice( "ALERT", 1000 );
- return;
-
- !
- ! This SUBROUTINE will hit every player in the group by using the
- ! subroutine HITPLAYER.
- !
- :HITGROUP
- foreach player do
- gosub HITPLAYER;
- endfor;
- return;
-
- !
- ! This SUBROUTINE will decrement the hit points of the current
- ! group member. It checks to see if the player has died or lost
- ! consciousnes. The variable S0 contains the reason for the hit.
- !
- :HITPLAYER
- if player.hp > 0 then
- dec( player.hp );
- if player.hp = 0 then
- writeln( player.name, " has died of ", s0, "!" );
- elsif player.hp = 1 then
- writeln( player.name, " has fainted from ", s0, "!" );
- else
- writeln( player.name, " weakens!" );
- endif;
- endif;
- return;
-
- !------------------------------------------------------------------------!
- !
- ! SUBROUTINE: M1_INVOKE
- !
- ! Type 1 Magic - Affects the person invoking the magic..
- !
- ! This code is equivalent to the one in OBJECT.SCR. When resting,
- ! rings and amulets that have magical properties will re-invoke their
- ! effect when you wake up.
- !
- !------------------------------------------------------------------------!
- :M1_INVOKE
- !------------------------------------------------------------------------!
-
- if curritem.cursed then
- if curritem.permanent then
- writeln( "WARNING: Cursed Item with permanent effect not recommended!");
- curritem.permanent = FALSE;
- endif;
- endif;
-
- if curritem.charges < 255 then
- dec(curritem.charges); ! 255 means forever !
- endif;
-
- on curritem.class goto
- M1_NONE, M1_CURE, M1_HEAL, M1_POISON, M1_RESTORE,
- M1_STR, M1_DEX, M1_SPD, M1_AIM, M1_AC,
- M1_HP, M1_IQ, M1_PWR;
-
- :M1_NONE
- return;
-
- :M1_CURE
- if player.poisoned then
- player.poisoned = 0;
- writeln( player.name, " is now cured." );
- endif;
- return;
-
- :M1_HEAL
- if player.hp > 0 and player.hp < player.mhp then
- if curritem.units > 0 then
- L(0) = curritem.units; ! always heals the same points !
- else
- L(0) = random(player.mhp - player.hp)+1; ! heal a random number of points !
- endif;
- if player.hp + L(0) < player.mhp then
- writeln( player.name, " heals ", L(0), " hit points.." );
- inc( player.hp, L(0) );
- else
- writeln( player.name, " has been completely healed!" );
- player.hp = player.mhp;
- endif;
- endif;
- return;
-
- :M1_POISON
- if NOT player.poisoned then
- player.poisoned = TRUE;
- writeln( player.name, " is poisoned!" );
- endif;
- return;
-
- :M1_RESTORE
- if player.hp < player.mhp then
- player.hp = player.mhp;
- writeln( player.name, " is completely healed!" );
- endif;
- return;
-
- :M1_STR
- if curritem.cursed then
- player.str = 0;
- else
- inc( player.str, curritem.units );
- if curritem.permanent then
- inc( player.mstr, curritem.units );
- endif;
- writeln( player.name, "'s strength increased by ", curritem.units, "!" );
- endif;
- return;
-
- :M1_DEX
- if curritem.cursed then
- player.dex = 0;
- else
- inc( player.dex, curritem.units );
- if curritem.permanent then
- inc( player.mdex, curritem.units );
- endif;
- writeln( player.name, "'s dexterity increased by ", curritem.units, "!" );
- endif;
- return;
-
- :M1_SPD
- if curritem.cursed then
- player.spd = 0;
- else
- inc( player.spd, curritem.units );
- if curritem.permanent then
- inc( player.mspd, curritem.units );
- endif;
- writeln( player.name, "'s speed increased by ", curritem.units, "!" );
- endif;
- return;
-
- :M1_AIM
- if curritem.cursed then
- player.aim = 0;
- else
- inc( player.aim, curritem.units );
- if curritem.permanent then
- inc( player.maim, curritem.units );
- endif;
- writeln( player.name, "'s aim increased by ", curritem.units, "!" );
- endif;
- return;
-
- :M1_AC
- if curritem.cursed then
- player.ac = 0;
- else
- inc( player.ac, curritem.units );
- if curritem.permanent then
- inc( player.mac, curritem.units );
- endif;
- writeln( player.name, "'s armor class increased by ", curritem.units, "!" );
- endif;
- return;
-
- :M1_HP
- if curritem.cursed then
- player.hp = player.hp / 3 + 1;
- else
- inc( player.hp, curritem.units );
- if curritem.permanent then
- inc( player.mhp, curritem.units );
- endif;
- writeln( player.name, "'s hit points increased by ", curritem.units, "!" );
- endif;
- return;
-
- :M1_IQ
- if curritem.cursed then
- player.iq = 0;
- else
- inc( player.iq, curritem.units );
- if curritem.permanent then
- inc( player.miq, curritem.units );
- endif;
- writeln( player.name, "'s i.q. increased by ", curritem.units, "!" );
- endif;
- return;
-
- :M1_PWR
- if player.class = ELF or player.class = WIZARD then
- if curritem.cursed then
- player.pwr = 0;
- else
- inc( player.pwr, curritem.units );
- if curritem.permanent then
- inc( player.mpwr, curritem.units );
- endif;
- writeln( player.name, "'s power increased by ", curritem.units, "!" );
- endif;
- else
- write( player.name, " has a headache all night long.." );
- if player.hp < 3 then
- writeln( " and dies!" );
- player.hp = 0;
- else
- writeln;
- dec( player.hp, 2 );
- endif;
- endif;
- return;
-
- !-----------------------------------------------------------------------!
- ! Allow ONE minute of time to go bye in the game's clock !
- !-----------------------------------------------------------------------!
- :CLOCK_TICK
-
- if minute < MinutesInAnHour - 1 then
- inc( minute );
- else
- minute = 0;
- if hour < HoursInADay - 1 then
- inc( hour );
- else
- hour = 0;
- if day < DaysInAMonth - 1 then
- inc( day );
- else
- day = 0;
- if month < MonthsInAYear - 1 then
- inc( month );
- else
- month = 0;
- inc( year );
- endif;
- endif;
- if hour = sunrise then
- writeln( "The sun rises in the east. " );
- ! gosub DAYNIGHT;
- elsif hour = sunset then
- writeln( "The sun sets in the west. " );
- ! gosub DAYNIGHT;
- endif;
- endif;
- endif;
- return;
-
- !-----------------------------------------------------------------------!
- ! Print the current time !
- !-----------------------------------------------------------------------!
- :CLOCK_PRINT
-
- L1 = HoursInADay / 2; ! Noon !
- if hour > L1 then
- if minute = 0 then
- writeln( "It's ", hour - L1, "pm" );
- elsif minute < 10 then
- writeln( "It's ", hour - L1, ":0", minute, "pm" );
- else
- writeln( "It's ", hour - L1, ":", minute, "pm" );
- endif;
- elsif hour = 0 then
- writeln( "It's midnight" );
- elsif hour = L1 then
- writeln( "It's noon" );
- else
- if minute = 0 then
- writeln( "It's ", hour, "am" );
- elsif minute < 10 then
- writeln( "It's ", hour, ":0", minute, "am" );
- else
- writeln( "It's ", hour, ":", minute, "am" );
- endif;
- endif;
- return;
- !
-
- !:DAYNIGHT
- !
- ! Ideally, we should reflect sunrise and sunset by some visual
- ! change in the game. For example:
- !
- ! If we wanted to create a "daylight"/"night-type" effect, we have
- ! two options. One, create two landscape sets that are identical
- ! except one uses darker colors (you really need 256 colors for
- ! this), as follows:
- !
- ! if world.type = OUTDOORS then
- ! if hour = sunrise then
- ! world.landscape = 0;
- ! elsif hour = sunset then
- ! world.landscape = 1;
- ! endif;
- ! endif;
- ! return;
- !
- ! The second one is to have a second PALETTE of colors, which
- ! are darker than the standard palette. You can then just
- ! change the palette
- !
- ! if hours = sunset then loadpalette( "NIGHT.PAL" );
- ! elsif hour = sunrise then loadpalette( "DAY.PAL" );
- ! return;
- !
- ! However, I did not implement 'loadpalette()' yet, so this last
- ! option is not possible right now. :)
- !
-
- !------------------------------------------------------
- ! Attack an NPC
- !------------------------------------------------------
-
- :ATTACK_NPC
- ! L3 contains distance to current npc per LOCATE command !
- ! L4 the weapon class (blunt, missile, etc)
- ! L5 the range (distance) you can reach with this weapon
- ! L6 is non-zero if type of ammo that is needed by the weapon
- ! L7 is the damage points done
- if player.weapon.count then
- L4 = player.weapon.class;
- L5 = player.weapon.range;
- L6 = player.weapon.ammoneeded;
- L7 = player.weapon.damage;
- else
- L4 = BLUNT;
- L5 = 1;
- L6 = 0;
- L7 = 1;
- endif;
- if L4 = MISSILE then
- for L10 = 0 to 15 do
- setbp( player, L10 );
- if player.bp.count then
- if player.bp.type = AMMO and player.bp.ammotype = L6 then
- if player.bp.count < 255 then
- dec(player.bp.count); ! Count of 255 means it never ends? !
- endif;
- L5 = max( L5, player.bp.range ); ! Use ammo's range if higher !
- inc( L7, player.bp.damage ); ! If ammunition causes extra damage !
- L6 = L10; ! Keep AMMO's BP here !
- goto FOUND_AMMO;
- endif;
- endif;
- endfor;
- writeln( "Out of ammo! Using hands!" );
- L4 = BLUNT;
- L5 = 1;
- L6 = 0;
- L7 = 1;
- :FOUND_AMMO
- endif;
- if L5 < L3 then
- writeln( "You have to get closer!" );
- stop;
- endif;
-
- ! HERE I COULD 'RANDOMIZE' THE DAMAGE, BUT I'LL LET IT BE CONSTANT FOR NOW !
-
- ! For contact weapons, STRENGTH increases damage !
- if L4 = BLUNT or L4 = EDGED then
- inc( L7, adjustments( player.str ) );
- endif;
-
- ! Now, we have to figure out if we missed !
- if L4 = MISSILE then
- ! For missile weapon, hit 5 out of 10, adjusted by AIM !
- if random( 10 ) + adjustments( player.aim ) < 5 then
- writeln( player.name, " missed.." );
- voice( "BadAim", 1000 );
- else
- gosub HIT_NPC;
- endif;
- else
- ! For non-missile weapon, hit 7 out of 10 adjusted up by the
- ! player's dexterity and down by the NPC's dexterity
- if random(10) + adjustments(player.dex) - adjustments(npc.dex) < 3 then
- writeln( player.name, " missed.." );
- voice( "Swish", 1000 );
- else
- gosub HIT_NPC;
- endif;
- endif;
- stop;
-
- :HIT_NPC
-
- L7 = max( L7, 1 ); ! At least one HP of damage !
- if npc.hp > 1 and npc.ac > 0 then ! Armor Class protects the NPC !
- L8 = random( npc.ac+1 ); ! Absorb 0 to npc.ac damage points !
- if L8 >= L7 then
- writeln( npc.type, "'s armor absorbs the impact!" );
- voice( "Clank", 1000 );
- return;
- endif;
- dec( L7, L8 ); ! Reduce damage by L8 amount !
- endif;
-
- ! Fast PLAYERS get to hit more than once !
- if player.spd > npc.spd then
- L9 = (player.spd - npc.spd) / 10 + 1;
- else
- L9 = 1;
- endif;
- while L9 > 0 and npc.count do
- if npc.hp > L7 then
- write( npc.type, " hit!" );
- dec( npc.hp, L7 );
- on random(3) gosub :V1, :V2, :V3;
- else
- write( npc.type, " killed!" );
- voice( "YouKill", 1000 );
- L7 = npc.hp;
- ! Now is the perfect time to GENERATE RANDOM TREASURE !
- gosub TREASURE;
- npc.count = 0; ! Actually Kill the NPC !
- endif;
- writeln( " (", L7, " points)" );
- inc( player.exp, L7 );
- dec(L9);
- endwhile;
-
- return;
-
- :V1 voice( "Argh", 1000 ); return;
- :V2 voice( "Ouch", 1000 ); return;
- :V3 voice( "Whoosh", 1000 ); return;
-
- !------------------------------------
- :TREASURE
- !------------------------------------
- ! Generate random treasure
-
- ! First, leave the contents of the NPCs backpack..
- foreach npc.bp do
- drop( npc.bp, -npc.count, npc.x, npc.y ); ! Drop a copy of this item
- endfor;
-
- ! Now generate a random treasure
- on random(4) goto GT_NONE, GT_GOLD, GT_CHEST, GT_SPECIAL;
- :GT_NONE
- return;
-
- :GT_GOLD
- new( object, npc.x, npc.y, GOLDSACK );
- object.weight = random( player.mhp ) + 1;
- object.value = object.weight * 10;
- return;
-
- :GT_CHEST
- new( object, npc.x, npc.y, CHEST );
- object.class = NORMAL_CHEST;
- object.weight = random( player.mhp ) + 1;
- object.value = object.weight * 10;
- object.locktype = random(2); ! 0=None, 1+ = Key !
- object.traptype = random(3); ! 0=None, 1=Poison, 2+ = Bomb !
- return;
-
- :GT_SPECIAL
- ! AMULET=5,RING=6,POTION=7,SCROLL=8,STAFF=9
- new( object, npc.x, npc.y, AMULET + random(5) );
- if object.type = SCROLL or object.type = STAFF then ! SCROLL or STAFF !
- object.class = random(15)+1; ! See OBJECT CLASS in DCCTOKEN.DAT !
- else
- object.class = random(12)+1; ! See OBJECT CLASS in DCCTOKEN.DAT !
- endif;
- object.weight = 1;
- if object.type = RING or object.type = AMULET or object.type = STAFF then
- object.charges = random( player.level ) + 1;
- endif;
- if object.type = RING or object.type = AMULET or object.type = POTION then
- object.units = random( player.mhp ) + 1;
- object.permanent = (random(100) = 0); ! One out of 100 !
- endif;
- if object.permanent then
- object.value = 1000;
- object.weight = 2;
- else
- object.value = 10;
- endif;
- return;
-
- !------------------------------------
- :NEW_LEVEL
- !------------------------------------
-
- L10 = 1; ! Start with level 1
- L11 = 200; ! Next level is at 200
- while L11 < player.exp do
- inc( L11, L11 ); ! Each level is TWICE as much as the previous one !
- inc( L10, 1 );
- endwhile;
- if L10 > player.level then ! New Level !
- L12 = random( player.level ) + 1; ! First, give some hit points !
- write( "New level! ", player.name, " gained ", L12, "hp " );
- inc( player.level );
- inc( player.mhp, L12 ); ! Permanent Increase !
- inc( player.hp, L12 ); ! Reflect the new HP immediatly !
-
- ! Now increase one ore more attributes depending on the class !
- L12 = random(player.level + 1) + 1; ! Start with this many points !
- if L12 > 5 then
- L12 = random(10); ! Make more than 5 points 'unlikely' but possible
- endif;
- on player.class goto
- :EX_HUMAN,
- :EX_ELF,
- :EX_DWARF,
- :EX_WIZARD,
- :EX_ARCHER,
- :EX_FIGHTER;
- endif;
- return; ! No new level !
-
- :EX_HUMAN ! Humans and 'unknown'
- inc( player.mstr, L12 );
- writeln( "and ", L12, " str." );
- return;
-
- :EX_ELF
- inc( player.miq, L12 + L12 ); ! Elf gains intelligence twice as fast !
- writeln( "and ", L12, " iq." );
- return;
-
- :EX_DWARF
- L13 = random(L12);
- inc( player.mstr, L12 - L13 ); ! Dwarf gains some strength !
- inc( player.mdex, L13 ); ! and some dexterity !
- writeln( ", ", L12 - L13, " str and ", L13, " dex." );
- return;
-
- :EX_WIZARD
- inc( player.miq, L12 ); ! Wizards gain intelligence !
- writeln( "and ", L12, " iq." );
- return;
-
- :EX_ARCHER
- L13 = random(L12);
- inc( player.maim, L12 - L13 ); ! Dwarf gains some aim !
- inc( player.mspd, L13 ); ! and some speed !
- writeln( ", ", L12 - L13, " aim and ", L13, " speed." );
- return;
-
- :EX_FIGHTER
- inc( L12, random(L12) ); ! Fighters gain strength more quickly !
- inc( player.mstr, L12 );
- writeln( "and ", L12, " str." );
- return;
-
- !
- ! Look at current bp object
- !
- :DESCRIBE
- if curritem.picture >= 0 then
- viewpcx( curritem );
- if success then
- pause;
- endif;
- paint(window); ! Assumes the picture fits in the window !
- elsif curritem.type = SIGN or curritem.type = BOOK then
- readtext( curritem.text );
- RETURN;
- endif;
- write( "You see a ", curritem.name );
- write( ", Type: ", curritem.type );
- !
- ! The following is a 'cascading if..then..elsif..elsif.....else..endif'
- ! statement. It is used here to illustrate it's usefulness. The same
- ! code could have been written with a 'ON object.type GOTO' statement.
- !
- if object.type = FOOD or object.type = POTION then
- if object.class then
- write( ", Class: ", object.class );
- if object.class <> CURE then
- write( ", Units: ", object.units );
- endif;
- endif;
- elsif object.type = WEAPON then
- write( ", Class: ", object.class,
- ", Hands: ", object.hands,
- ", Range: ", object.range,
- ", Damage: ", object.damage );
- if object.ammoneeded then
- write( ", Needs ammo type: ", object.ammo_type );
- endif;
- elsif object.type = AMMO then
- write( ", Ammo Type: ", object.ammotype );
- if object.traptype then
- write( ", Poisoned" );
- endif;
- if object.damage then
- write( ", Extra Damage: ", object.damage );
- endif;
- elsif object.type = ARMOR or object.type = SHIELD then
- write( ", Armor Class: ", object.ac );
- if object.cursed then
- write( " Cursed!" );
- endif;
- elsif object.type = AMULET or object.type = RING or object.type = GEMS then
- if object.class then
- write( ", Class: ", object.class );
- write( ", Charges: ", object.charges );
- if object.class <> CURE then
- write( ", Units: ", object.units );
- if object.permanent then
- write( ", Permanent!" );
- else
- write( ", Temporary" );
- endif;
- endif;
- if object.cursed then
- write( ", Cursed!" );
- endif;
- endif;
- elsif object.type = SCROLL then
- write( ", Class: ", object.class );
- elsif object.type = STAFF then
- write( ", Class: ", object.class, ", Charges: ", object.charges );
- elsif object.type = CHEST then
- if object.locktype then
- write( ", Locked!" );
- if object.traptype = 0 then
- write( ", no traps" );
- elsif object.traptype = 1 then
- write( ", poison trap" );
- else
- write( ", bomb damage: ", object.traptype );
- endif;
- endif;
- ! elsif object.type = KEYS then
- ! nothing special about it
- ! elsif object.type = BOOK then
- ! nothing special about it
- ! elsif object.type = GOLDSACK then
- ! nothing special about it
- ! elsif object.type = TORCH then
- ! nothing special about it
- ! elsif object.type = LANTERN then
- ! nothing special about it
- ! elsif object.type = ROPE then
- ! nothing special about it
- ! elsif object.type = HOOKS then
- ! nothing special about it
- ! elsif object.type = MIRROR then
- ! nothing special about it
- ! elsif object.type = SIGN then
- ! nothing special about it
- elsif object.type = VEHICLE then
- write( ", Class: ", object.class );
- ! else
- ! user defined type?
- endif;
- if object.weight > 1 and object.weight < 256 then
- write( ", Weight: ", object.weight );
- endif;
- writeln( "." );
- return;
-
- !
- ! MOVING THE CHARACTERS
- !
-
- :MOVE_UP
- L3 = 0; L4 = -1; goto DO_MOVE;
-
- :MOVE_DN
- L3 = 0; L4 = 1; goto DO_MOVE;
-
- :MOVE_LF
- L3 = -1; L4 = 0; goto DO_MOVE;
-
- :MOVE_RT
- L3 = 1; L4 = 0; goto DO_MOVE;
-
- :MOVE_UL
- L3 = -1; L4 = -1; goto DO_MOVE;
-
- :MOVE_DL
- L3 = -1; L4 = 1; goto DO_MOVE;
-
- :MOVE_UR
- L3 = 1; L4 = -1; goto DO_MOVE;
-
- :MOVE_DR
- L3 = 1; L4 = 1; goto DO_MOVE;
-
- :DO_MOVE
- L0 = player.x + L3;
- L1 = player.y + L4;
- if world.wrap_around then
- if L0 < 0 then
- gosub NOTFIGHTING;
- L0 = world.x - 1;
- elsif L0 >= world.x then
- gosub NOTFIGHTING;
- L0 = 0;
- endif;
- if L1 < 0 then
- gosub NOTFIGHTING;
- L1 = world.y - 1;
- elsif L1 >= world.y then
- gosub NOTFIGHTING;
- L1 = 0;
- endif;
- else
- if L0 < 0 or L0 >= world.x or L1 < 0 or L1 >= world.y then
- gosub NOTFIGHTING;
- writeln( "Do you wan't to leave ", world.name, "?" );
- if select( "Yes", "No" ) = 0 then
- world.door = world.edge_door;
- runscript( WORLD, "WORLDDEF", EXIT );
- !
- ! NOTE: We could just run "enter( world.edge_door );" instead
- ! of the above two lines. The difference is that when you
- ! run ENTER( door ), the driver does NOT call the @EXIT
- ! routine in the current world. A minor but important
- ! difference. The reason for this, is that the behaviour of
- ! ENTERING A WORLD (i.e. load the world, call script at @GET,
- ! call script at @ENTER) is a feature of the driver, but
- ! the @EXIT entry point is handled entirely by the scripts
- ! themselves. If you don't want to take any action when you
- ! exit a world, you can change the above two lines to a
- ! simple call to the ENTER() function.
- !
- endif;
- stats(-1);
- STOP;
- endif;
- endif;
- !
- ! Use a LOOP through all the NPCs, to see if there is one
- ! standing at that spot or a guard NEAR the spot
- !
- L2 = locate( npc, L0, L1 ); ! Is there an object at L0,L1? !
- if L2 >= 0 then
- writeln( "There is someone standing in your way!" );
- STOP;
- endif;
- ! Check for guards !
- ! The following loop works fine, but it selects every NPC in the
- ! world, loading it's statistics record into memory and causing
- ! a disk access. While the game driver has a small cache of stat
- ! records, it still is better to avoid a 'foreach' loop on the
- ! NPCs in the control script. Note that you can use foreach on
- ! the players and objects because they are already in memory.
- ! -> THIS WORKS, BUT CAUSES UNNECESARY DISK ACCESS
- ! foreach NPC do
- ! if npc.type = GUARD then
- ! if abs(npc.x - L0) < 2 and abs(npc.y - L1) < 2 then
- ! writeln( "There is a GUARD there!" );
- ! STOP;
- ! endif;
- ! endif;
- ! endfor;
- ! The following is better. It uses a new feature of the LOCATE
- ! command. If you provide an X,Y coordinate, it looks for the
- ! specified NPC or OBJECT at the given location. It only causes
- ! a disk access if there is an NPC at that location, and that
- ! NPC has a much better chance of having it's record cached.
- ! -> MUCH BETTER:
- if L3 then ! Moving on X !
- L2 = locate( npc, L0+L3, L1 );
- if success then gosub check_guard; endif;
- L2 = locate( npc, L0+L3, L1+1 );
- if success then gosub check_guard; endif;
- L2 = locate( npc, L0+L3, L1-1 );
- if success then gosub check_guard; endif;
- endif;
- if L4 then ! Moving on Y !
- L2 = locate( npc, L0 , L1+L4 );
- if success then gosub check_guard; endif;
- L2 = locate( npc, L0+1, L1+L4 );
- if success then gosub check_guard; endif;
- L2 = locate( npc, L0-1, L1+L4 );
- if success then gosub check_guard; endif;
- endif;
- !
- ! No find if there are any OBJECTS at the X, Y location.
- !
- L2 = locate( object, L0, L1 ); ! Is there an object at L0,L1? !
- if L2 >= 0 then
- ! Check for locked doors
- if object.type = DOOR and object.locktype > 0 then
- writeln("The door is locked!" );
- STOP;
- endif;
- ! Check for fences and things, both of which we should not
- ! be able to walk over.
- if object.type = FENCE or object.type = THING then
- writeln( "There is a ", object.name, " in your way" );
- STOP;
- endif;
- endif;
- !
- ! Now check the world's density and see if we can walk over it
- ! considering the type of landscape and the vehicle (if any)
- !
- L2 = world.density(L0,L1);
- if L2 = WALL or L2 = LOCKED_DOOR or L2 = HIDDEN_DOOR then
- STOP; ! Can't Move !
- endif;
- on group.vehicle.class goto
- CHK_WALK, CHK_MOUNT, CHK_ATV, CHK_LFLY, CHK_MFLY, CHK_HFLY, CHK_RAFT, CHK_BOAT;
- ! Anything else, don't allow the move !
- STOP;
- ! -- ON WATER -- !
- :CHK_RAFT
- if L2 = LOW_WATER or L2 = ROUGH_WATER goto CHK_OK;
- STOP;
- :CHK_BOAT
- if L2 = DEEP_WATER goto CHK_OK;
- STOP;
- ! -- BY AIR -- !
- :CHK_LFLY
- if L2 = DEEP_WATER then STOP; endif;
- ! Drop Through !
- :CHK_MFLY
- if L2 = VERY_HIGH then STOP; endif;
- ! Drop Through !
- :CHK_HFLY
- goto CHK_OK;
- :CHK_WALK
- if L2 = FLAT or L2 = DESERT or L2 = SWAMP goto CHK_OK;
- if L2 = ROUGH and random(3) <> 0 or
- L2 = VERY_ROUGH and random(3) = 0 goto CHK_OK;
- if L2 = ROUGH or L2 = VERY_ROUGH then
- writeln( "Rough terrain.." );
- endif;
- ! Anything else, don't allow the move !
- STOP;
- :CHK_MOUNT
- if L2 = FLAT or
- L2 = ROUGH or
- L2 = VERY_ROUGH and random(3) <> 0 then ! 2 out of 3 !
- goto CHK_OK;
- endif;
- if L2 = VERY_ROUGH then
- writeln( "Very rough terrain.." );
- endif;
- STOP;
- :CHK_ATV
- if L2 = FLAT or L2 = ROUGH or L2 = VERY_ROUGH or L2 = LOW_WATER then
- goto CHK_OK; ! All Terrain Vehicle !
- endif;
- ! Anything else, don't allow the move !
- STOP;
-
- :CHECK_GUARD
- !
- ! From GUARD.SCR, npc.v1 = 1 means you have given the password to the
- ! guard, so you can pass. npc.v1 = 2 means you have given a BRIBE to
- ! the guard, so you can also pass.
- !
- if npc.type = GUARD and npc.v1 = 0 then
- writeln( "npc.name=",npc.name,", npc.v0=",npc.v0," npc.v1=",npc.v1);
- writeln( "There is a GUARD there!" );
- STOP;
- endif;
- return;
- :CHK_OK
- ! Go Ahead and Move
- if fighting then
- if group.vehicle.count then ! Inside a vehicle !
- group.x = L0; group.y = L1;
- else
- player.x = L0; player.y = L1;
- endif;
- else
- group.x = L0; group.y = L1;
- ! Check for Trap doors !
- if L0 > 0 and L1 > 0 then
- for L5 = 0 to 31 do
- if L0 = world.doorx(L5) and L1 = world.doory(L5) then
- if world.trapdoorswitch(L5) then
- world.door = L5; ! Use this door !
- runscript( WORLD, "WORLDDEF", EXIT );
- endif;
- endif;
- endfor;
- endif;
- endif;
- STOP;
-
- :NOTFIGHTING
- if fighting then
- writeln( "You can't leave during a fight.." );
- stop;
- endif;
- return;
-
- :FKEY1
- ! Help !
- writeln( "The following commands are defined:" );
- write( "A)ttack, ");
- write( "C)amp, ");
- write( "D)rop, ");
- write( "E)nter, ");
- write( "G)et, ");
- write( "I)nventory, ");
- write( "L)ook, ");
- write( "iN)voike, ");
- write( "Q)uaff (eat or drink), ");
- write( "R)emove, ");
- write( "S)pell, ");
- write( "T)alk, ");
- write( "U)se, ");
- write( "V)acate, ");
- write( "W)ield/Wear, ");
- write( "eX)it, ");
- write( "Z)ap (with staff),");
- write( "F1=Help, ", "F2=Save, ", "F3=Sound, ", "F4=Restore, ",
- "F6=Restart, ", "F10=Exit" );
- writeln;
- STOP;
-
- :FKEY2
- L0 = getnum( "Save in what slot?", 0, 999 );
- if L0 >= 0 then
- save( L0 );
- stop;
- endif;
- continue;
-
- :FKEY3
- sound = not sound;
- if sound then
- writeln( "Sound is now on!" );
- else
- writeln( "Sound is now off!" );
- endif;
- stop;
-
- :FKEY4
- L0 = getnum( "Restore from what slot?", 1, 999 );
- if L0 > 0 then
- restore( L0 );
- writeln( "RESTORE OF SLOT ", L0, " FAILED!" );
- endif;
- stop;
-
- :FKEY5
- stop;
-
- :FKEY6
- writeln( "Do you really want to RESTART?" );
- L0 = select( "Yes", "No" );
- if L0 = 0 then
- restart;
- writeln( "RESTART FAILED!" );
- endif;
- stats(-1);
- stop;
-
- :FKEY7
- foreach player do
- player.level = 10;
- endfor;
- stop;
-
- :FKEY8
- savepcx( "SAVESCRN.PCX" );
- stop;
-
- :FKEY9
- runscript( "TEST", 0 );
- stop;
-
- :FKEY10
- if fighting then
- writeln( "Press ESCape to stop the fight, then F10 to exit!" );
- stop;
- endif;
- writeln( "See you later..." );
- save(0);
- end_game;
-
-